/**
 * 依赖解析器
 * 
 * 智能解析源文件的依赖关系，提取相关的头文件内容
 */

import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';
import { Logger } from '../../../src/logger/Logger';

export interface ResolvedDependency {
    type: 'header' | 'local-include' | 'system-include';
    fileName: string;
    content?: string;  // 如果成功读取
    path?: string;     // 文件路径
}

export class DependencyResolver {
    private static readonly MAX_HEADERS = 3;  // 最多提取3个头文件
    private static readonly MAX_FILE_SIZE = 50000;  // 单个头文件最大50KB
    
    /**
     * 解析源文件的依赖（智能多层策略）
     * 
     * @param sourceFilePath 源文件路径
     * @param sourceContent 源文件内容
     * @returns 解析到的依赖列表
     */
    public static async resolveDependencies(
        sourceFilePath: string,
        sourceContent: string
    ): Promise<ResolvedDependency[]> {
        const dependencies: ResolvedDependency[] = [];
        
        // === P0: 同名头文件（必须） ===
        const headerFile = await this.findHeaderFile(sourceFilePath);
        if (headerFile) {
            dependencies.push(headerFile);
            Logger.info(`[DependencyResolver] ✅ P0: 找到同名头文件: ${headerFile.fileName}`);
        }
        
        // === P1: 本地头文件（#include "xxx.h"）===
        const localIncludes = await this.extractLocalIncludes(sourceFilePath, sourceContent);
        if (localIncludes.length > 0) {
            Logger.info(`[DependencyResolver] ✅ P1: 找到 ${localIncludes.length} 个本地头文件`);
            dependencies.push(...localIncludes.slice(0, this.MAX_HEADERS - dependencies.length));
        }
        
        Logger.info(`[DependencyResolver] 📊 总共解析到 ${dependencies.length} 个依赖`);
        
        return dependencies;
    }
    
    /**
     * P0: 查找同名头文件（xxx.cpp → xxx.h）
     */
    private static async findHeaderFile(sourceFilePath: string): Promise<ResolvedDependency | null> {
        const ext = path.extname(sourceFilePath);
        const baseName = sourceFilePath.replace(ext, '');
        
        // 尝试常见的头文件扩展名
        const headerExtensions = ['.h', '.hpp', '.hxx'];
        
        for (const headerExt of headerExtensions) {
            const headerPath = baseName + headerExt;
            
            if (fs.existsSync(headerPath)) {
                try {
                    const stat = fs.statSync(headerPath);
                    
                    // 检查文件大小
                    if (stat.size > this.MAX_FILE_SIZE) {
                        Logger.warn(`[DependencyResolver] ⚠️ 头文件过大，跳过: ${path.basename(headerPath)} (${(stat.size / 1024).toFixed(1)} KB)`);
                        return {
                            type: 'header',
                            fileName: path.basename(headerPath),
                            path: headerPath
                            // content 为空，表示文件太大
                        };
                    }
                    
                    const content = fs.readFileSync(headerPath, 'utf-8');
                    
                    return {
                        type: 'header',
                        fileName: path.basename(headerPath),
                        content: content,
                        path: headerPath
                    };
                } catch (error) {
                    Logger.warn(`[DependencyResolver] ⚠️ 读取头文件失败: ${headerPath}`);
                }
            }
        }
        
        return null;
    }
    
    /**
     * P1: 提取本地头文件（#include "xxx.h"）
     */
    private static async extractLocalIncludes(
        sourceFilePath: string,
        sourceContent: string
    ): Promise<ResolvedDependency[]> {
        const dependencies: ResolvedDependency[] = [];
        const sourceDir = path.dirname(sourceFilePath);
        
        // 匹配 #include "xxx.h" 格式（本地头文件）
        const includeRegex = /#include\s+"([^"]+)"/g;
        
        const matches = [...sourceContent.matchAll(includeRegex)];
        
        for (const match of matches) {
            if (dependencies.length >= this.MAX_HEADERS) {
                break;
            }
            
            const includePath = match[1];
            
            // 跳过已处理的同名头文件
            const includeBaseName = path.basename(includePath, path.extname(includePath));
            const sourceBaseName = path.basename(sourceFilePath, path.extname(sourceFilePath));
            if (includeBaseName === sourceBaseName) {
                continue;
            }
            
            // 尝试解析路径
            const possiblePaths = [
                path.join(sourceDir, includePath),  // 相对于源文件
                path.join(sourceDir, '..', 'include', includePath),  // ../include/
                path.join(sourceDir, '..', includePath),  // ../
            ];
            
            for (const possiblePath of possiblePaths) {
                if (fs.existsSync(possiblePath)) {
                    try {
                        const stat = fs.statSync(possiblePath);
                        
                        if (stat.size > this.MAX_FILE_SIZE) {
                            Logger.warn(`[DependencyResolver] ⚠️ 本地头文件过大，跳过: ${includePath}`);
                            dependencies.push({
                                type: 'local-include',
                                fileName: includePath,
                                path: possiblePath
                            });
                            break;
                        }
                        
                        const content = fs.readFileSync(possiblePath, 'utf-8');
                        
                        dependencies.push({
                            type: 'local-include',
                            fileName: includePath,
                            content: content,
                            path: possiblePath
                        });
                        
                        Logger.info(`[DependencyResolver]    ✓ 本地头文件: ${includePath}`);
                        break;
                    } catch (error) {
                        // 继续尝试下一个路径
                    }
                }
            }
        }
        
        return dependencies;
    }
    
    /**
     * 格式化依赖供 LLM 使用
     */
    public static formatForLLM(
        sourceFile: string,
        sourceContent: string,
        dependencies: ResolvedDependency[]
    ): string {
        if (dependencies.length === 0) {
            return sourceContent;
        }
        
        let formatted = `// ===== 主要源文件 =====\n`;
        formatted += `// 文件: ${path.basename(sourceFile)}\n\n`;
        formatted += `${sourceContent}\n\n`;
        
        formatted += `// ===== 依赖的头文件（${dependencies.length}个）=====\n`;
        formatted += `// 这些头文件包含了类定义、成员变量、函数声明等\n\n`;
        
        for (const dep of dependencies) {
            formatted += `// --- ${dep.type}: ${dep.fileName} ---\n`;
            
            if (dep.content) {
                formatted += `${dep.content}\n\n`;
            } else {
                formatted += `// (文件过大或无法读取，但可以从文件名推断相关定义)\n`;
                if (dep.path) {
                    formatted += `// 路径: ${dep.path}\n`;
                }
                formatted += `\n`;
            }
        }
        
        return formatted;
    }
    
    /**
     * 简化格式（仅列出依赖，不展开内容）
     */
    public static formatDependencyList(dependencies: ResolvedDependency[]): string {
        if (dependencies.length === 0) {
            return '';
        }
        
        let list = `\n**依赖的头文件**：\n`;
        for (const dep of dependencies) {
            if (dep.type === 'header') {
                list += `- 📄 同名头文件: \`${dep.fileName}\` ${dep.content ? '(已加载)' : '(文件过大)'}\n`;
            } else if (dep.type === 'local-include') {
                list += `- 📎 本地包含: \`${dep.fileName}\` ${dep.content ? '(已加载)' : '(文件过大)'}\n`;
            }
        }
        
        return list;
    }
}

